home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / apps / 42 / wind2.prf < prev    next >
Text File  |  1986-07-17  |  21KB  |  393 lines

  1. .!****************************************************************************
  2. .! 
  3. .! ANTIC PUBLISHING INC., COPYRIGHT 1985.  REPRINTED BY PERMISSION.
  4. .!
  5. .! ** Professional GEM ** by Tim Oren
  6. .!
  7. .! Proff File by ST enthusiasts at
  8. .! Case Western Reserve University
  9. .! Cleveland, Ohio
  10. .! uucp : decvax!cwruecmp!bammi
  11. .! csnet: bammi@case
  12. .! arpa : bammi%case@csnet-relay
  13. .! compuserve: 71515,155
  14. .!
  15. .!****************************************************************************
  16. .!
  17. .!
  18. .!****************************************************************************
  19. .!
  20. .!            Begin Part 2
  21. .!
  22. .!****************************************************************************
  23. .!
  24. .PART II Windows
  25. .SH EXCELSIOR
  26. In this installment, we continue the exploration of GEM's window manager by
  27. finding out how to process the messages received by an application
  28. when it has a window defined on the screen.
  29. .PP
  30. Also, beginning with this column, sample C code demonstrating the techniques
  31. discussed will be available on SIG*ATARI in DL5.  This will allow you to
  32. download the code without interference by the CIS text-formatter used by ANTIC
  33. ONLINE output.
  34. .PP
  35. The file for this column is GEMCL2.XMO.  All references  to non-GEM routines in
  36. this column refer to this file.  Please note that  these files will not contain
  37. entire programs.  Instead, they consist of small pieces of utility code which
  38. you may copy and modify in your own  programs.
  39. .SH REDRAWING WINDOWS
  40. One of the most misunderstood parts of GEM is the correct method for drawing
  41. within a window.  Most requests for redrawing are generated by the GEM system,
  42. and arrive as messages (read with evnt_multi) which contain the handle of the
  43. window, and the screen rectangle which is  "dirty" and needs to be redrawn.
  44. .PP
  45. Screen areas may become dirty as a result of windows being closed, sized down,
  46. or moved, thus "exposing" an area underneath.  The completion of  a dialog, or
  47. closing of a desk accessory may also free up a screen area which needs to be
  48. redrawn.  When GEM detects the presence of a dirty rectangle,  it checks its
  49. list of open windows, and sends the application a redraw message  for each of
  50. its windows which intersects the dirty area.
  51. .SH CAVEAT EMPTOR
  52. GEM does not "clip" the rectangle which it sends to  the application; that is,
  53. the rectangle may not lie entirely within the  portion of the window which is
  54. exposed on the screen.  It is the job of the application to determine in what
  55. portion of the rectangle it may safely draw.   This is done by examining the
  56. "rectangle list" associated with the window.
  57. .PP
  58. A rectangle list is maintained by GEM for each active window.  It contains the
  59. portions of the window's interior which are exposed, i.e., topmost, on the
  60. screen and within which the app may draw.
  61. .PP
  62. Let's consider an example to make this clear.  Suppose an app has opened two
  63. windows, and there are no desk accessory windows open. The window which is
  64. topmost will  always have only one rectangle in its list.  If the two are
  65. separate on the  screen, then the second window will also have one rectangle.
  66. If they overlap,  then the top window will "break" the rectangle of the bottom
  67. one.  If the  overlap is at a corner, two rectangles will be generated for the
  68. bottom window.  If the overlap is on a side only, then three rectangles are
  69. required to cover  the exposed portion of the bottom window.  Finally, if the
  70. first window is  entirely within the second, it requires four rectangles in the
  71. list to tile the second window.
  72. .PP
  73. Try working out a few rectangle examples with pencil and paper to get the feel
  74. of it.  You will see that the possible combinations with more  than two windows
  75. are enormous.  This, by the way, is the reason that GEM does  not send one
  76. message for each rectangle on the list: With multiple windows,  the number of
  77. messages generated would quickly fill up the application's message queue.
  78. .PP
  79. Finally, note that every app MUST use this method, even if it only
  80. uses a single window, because there may be desk accessories with their
  81. own  windows in the system at the same time.  If you do not use the
  82. rectangle lists, you may overwrite an accessory's window.
  83. .SH INTO THE BITS
  84. First, we should note that the message type for a  redraw request is WM_REDRAW,
  85. which is stored in msg[0], the first location of the message returned by
  86. evnt_multi.  The window handle is stored in msg[3].  These locations are the
  87. same for all of the message types being discuss.  The rectangle which needs to
  88. be redrawn is stored in msg[4] through msg[7].
  89. .PP
  90. Now let's examine the sample redraw code in more detail. The redraw loop is
  91. bracketed with mouse off and mouse on calls.  If you forget to do  this, the
  92. mouse pointer will be over-written if it is within the window and  the next
  93. movement of the mouse will leave a rectangular blotch on the screen  as a piece
  94. of the "old" screen is incorrectly restored.
  95. .PP
  96. The other necessary step is to set the window update flag.  This prevents the
  97. menu manager from dropping a menu on top of the screen portion being redrawn.
  98. You must release this flag at the end of the redraw, or the you will be unable
  99. to use any menus afterwards.
  100. .PP
  101. The window rectangles are retrieved using a get-first, get-next scheme which
  102. will be familiar if you have used the GEM DOS or PC-DOS wildcard file calls.
  103. The end of the rectangle list has been reached when both the width and height
  104. returned are zero.  Since some part of a  window might be off-screen
  105. (unless you have clamped its position - see below), the retrieved
  106. rectangle is intersected with the desktop's area,  and then with the
  107. screen area for which a redraw was requested.
  108. .PP
  109. Now you have the particular area of the screen in which it is  legal to draw.
  110. Unless there is only one window in your application, you will have to test the
  111. handle in the redraw request to figure out what to  put in the rectangle.
  112. .PP
  113. Depending on the app, you may be drawing an AES  object tree, or executing VDI
  114. calls, or some combination of the two.  In  the AES case, the computed
  115. rectangle is used to specify the bounds of the objc_draw.  For VDI
  116. work, the rectangle is used to set the clipping area before executing
  117. the VDI calls.
  118. .SH A SMALL CONFESSION
  119. At the beginning of this discussion, I  deliberately omitted one class of
  120. redraws: those initiated by the application  itself.
  121. In some cases a part of the screen must be redrawn immediately to give feedback
  122. to the user following a keystroke, button, or mouse action.   In these cases,
  123. the application could call do_redraw directly, without  waiting for a message.
  124. .PP
  125. The only time you can bypass do_redraw, and draw  without walking the rectangle
  126. list, is when you can be sure that the target  window is on top, and that the
  127. figure being drawn is entirely contained  within it.
  128. .PP
  129. In many cases, however, an application initiated redraw happens because of a
  130. computed change, for instance, a spreadsheet update, and its timing is not
  131. crucial.  In this instance, you may wish to have the  app send ITSELF a redraw
  132. request.
  133. .PP
  134. The main advantage of this approach  is that the AES is smart enough to see if
  135. there is already a redraw request for the same window in the queue, and, if so,
  136. to merge the requests by  doing a union of their rectangles.  In this fashion,
  137. the "blinky" appearance of multiple redraws is avoided, without the need to
  138. include logic for merging redraws within the program.
  139. A utility routine for sending the "self-redraw" is included in the
  140. down-load for this article.
  141. .SH WINDOW CONTROL REQUESTS
  142. An application is notified by the AES, via the message system, when the user
  143. manipulates one of the window control points.  Remember that you must have
  144. specified each control point when the window was created, or will not receive
  145. the associated control message.
  146. .PP
  147. The most important thing to understand about window control is that the change
  148. which the user requested does not take place until the application forwards it
  149. to the AES.  While this makes for a little extra work,  it gives the program a
  150. chance to intervene and validate or modify the request to suit.
  151. .PP
  152. A second thing to keep in mind is that not all window updates cause a redraw
  153. request to be generated for the window, because the AES attempts to save time
  154. with raster moves on the screen.
  155. Now let's look at each window control request in detail.  The message
  156. code for a window move is WM_MOVED.  If you are willing to accept  any
  157. such request, just do:
  158. .FB wind_set()
  159. wind_set(wh, WF_CXYWH, msg[4], msg[5], msg[6], msg[7]);
  160. .FE
  161. .sp 1
  162. .ce 1
  163. (Remember that wh, the window handle, is always in msg[3]).
  164. .sp 1
  165. The AES will not request a redraw of the window following this call, unless the
  166. window is being moved from a location which is partially "off-screen". Instead,
  167. it will do a "blit" (raster copy) of the window and its contents to the new
  168. location without intervention by the app.
  169. .PP
  170. There are two constraints which you may often wish to apply to  the user's move
  171. request.  The first is to force the new location to lie entirely within the
  172. desktop, rather than partially off-screen.  You can do this with the
  173. rc_constrain utility by executing:
  174. .FB rc_constrain()
  175. rc_constrain(&full, &msg[4]);
  176. .FE
  177. before making the wind_set call.  (Full is assumed to contain the desktop
  178. dimensions.)
  179. .PP
  180. The second common constraint is to "snap" the x-dimension location of the new
  181. location to a word boundary.  This operation will speed up GEM's "blit" because
  182. no shifting or masking will need to be done when moving the window.  To perform
  183. this operation, use align() before the  wind_set call:
  184. .FB align()
  185. msg[4] = align(msg[4], 16);
  186. .FE
  187. The message code for a window size request is WM_SIZED.  Again, if you are
  188. willing to accept any request, you can just "turn it around" with the same
  189. wind_set call as given for WM_MOVED.
  190. .PP
  191. Actually, GEM enforces a couple of constraints on sizing.  First, the
  192. window may not be sized off screen.  Second, there is a minimum window
  193. size which is dependent on the window components specified when it was
  194. created.  This prevents features like scroll arrows from being
  195. squeezed into oblivion. The most common application constraint on
  196. sizing is to snap the size to horizontal words (as above) and/or
  197. vertical character lines.  In the latter case, the vertical dimension
  198. of the output font is used with align(). 
  199. .PP
  200. Also,  be aware that the size message which you receive specifies the
  201. EXTERNAL dimensions of the window.  To assure an "even" size for the
  202. INTERNAL dimensions, you must make a wind_calc call to compute them,
  203. use align() on the computed values, back out the corresponding
  204. external dimensions with the reverse wind_calc, and then make the
  205. wind_set call with this set of values. 
  206. .PP
  207. A window resize will only cause a redraw request for the window if the size is
  208. being increased in at least one dimension.  This is satisfactory for most
  209. applications, but if you must "reshuffle" the window after a  size-down, you
  210. should send yourself a redraw (as described above) after you make the wind_set
  211. call.  This will guarantee that the display is updated correctly.  Also note
  212. that the sizing or movement of one window may cause redraw requests to be
  213. generated for other windows which are uncovered by the change.
  214. .PP
  215. The window full request, with code WM_FULLED, is actually a toggle. If the
  216. window is already at its full size (as specified in the wind_create), then this
  217. is a request to shrink to its previous size. If the window is currently small,
  218. then the request is to grow to full size.
  219. .PP
  220. Since the AES records the current, previous, and maximum window size,
  221. you can use wind_get calls to determine which situation pertains. The
  222. hndl_full utility in the down-load (modified from Doodle), shows how
  223. to do this. 
  224. .PP
  225. The "zoom box" effects when changing size are optional, and can be removed  to
  226. speed things up.  Again, if the window's size is decreasing, no redraw is
  227. generated, so you must send yourself one if necessary.  You should not have  to
  228. perform any constraint or "snap" operations here, since (presumably) the  full
  229. and previous sizes have had these checks applied to them already.
  230. .PP
  231. The WM_CLOSED message is received when the close box is clicked. What
  232. action you perform depends on the application.  If you want to remove
  233. the window, use wind_close as described in the last column.  In many
  234. applications, however, the close message may indicate that a file is
  235. to be saved, or a directory or editing level is to be closed.  In
  236. these cases, the message is used to trigger this action before or
  237. instead of the wind_close.  (Folders on the Desktop are an example of
  238. this situation.) 
  239. .PP
  240. The WM_TOPPED message indicates that the AES wants to bring the
  241. indicated window to the "top" and make it active.  This happens if the
  242. user clicks within a window which is not on top, or if the currently
  243. topped window is closed by its application or desk accessory.
  244. Normally, the application should respond to this message with:
  245. .FB wind_set()
  246. wind_set(wh, WF_TOP, 0, 0);
  247. .FE
  248. and allow the process to complete.
  249. .PP
  250. In a few instances, a window may be used in an output only mode, such as a
  251. status display, with at least one other window present for input.  In
  252. this case, a WM_TOPPED message for the status window may be ignored.
  253. In all other cases, you must handle the WM_TOPPED message even if your
  254. application has only one window: Invocation of a desk accessory could
  255. always place another window on top.  If you fail to do so, subsequent
  256. redraws for your window may not be processed correctly.
  257. .SH WINDOW SLIDER MESSAGES
  258. If you specify all of the slider bar parts for your window, you may receive up
  259. to five different message types for each of the two sets of sliders.  To
  260. simplify things a little, I will discuss everything in terms of the vertical
  261. (right hand side) sliders.  If you are also using the horizontal sliders, the
  262. same techniques will work, just use the alternate mnemonics.
  263. .PP
  264. The WM_VSLID message indicates that the user has dragged the slider bar within
  265. its box, indicating a new relative position within the document.
  266. Along with the window handle, this message includes the relative
  267. position between 1 and 1000 in msg[4].
  268. .PP
  269. Recall from last column's discussion that this interval corresponds to the
  270. "freedom of movement" of the slider. If you want to accept the user's request,
  271. just make the call:
  272. .FB wind_set
  273. wind_set(wh, WF_VSLIDE, msg[4], 0, 0, 0);
  274. .FE
  275. .sp 1
  276. .ce 1
  277. (Corresponding horizontal mnemonics are WM_HSLID and WF_HSLIDE).
  278. .sp 1
  279. Note that this wind_set call will not cause a redraw message to be sent.  You
  280. must update the display to reflect the new scrolled position, either by
  281. executing a redraw directly, or by sending yourself a message.
  282. .PP
  283. If the document within the window has some structure, you may not wish
  284. to accept all slider positions.  Instead you may want to force the
  285. scroll position to the nearest text line (for instance).  Using terms
  286. defined in the last column, you may convert the slider position to
  287. "document units" with: 
  288. .sp 1
  289. .ce 1
  290. top_wind = msg[4] * (total_doc - seen_doc) / 1000 + top_doc
  291. .sp 1
  292. .ce 1
  293. (This will probably require 32-bit arithmetic).
  294. .sp 1
  295. After rounding off or otherwise modifying the request, convert it back
  296. to slider units and make the WF_VSLIDE request.
  297. .PP
  298. The other four slider requests all share one message code: WM_ARROWED.
  299. They are distinguished by sub-codes stored in msg[4]: WA_UPPAGE,
  300. WA_DNPAGE, WA_UPLINE, and WA_DNLINE.  These are produced by clicking
  301. above and below the slider, and on the up and down arrows,
  302. respectively.  (I have no idea why sub-codes were used in this one
  303. instance.)  The corresponding horizontal slider codes are: 
  304. WA_LFPAGE, WA_RTPAGE, WA_LFLINE, and WA_RTLINE.
  305. .PP
  306. What interpretation you give to these requests will depend on  the application.
  307. In the most common instance, text documents, the customary method is to change
  308. the top of window position (top_wind) by  one line for a WA_UPLINE or
  309. WA_DNLINE, and by seen_doc (the number of lines in the window) for a
  310. WA_UPPAGE or WA_DNPAGE.
  311. .PP
  312. After making the change, compute a new slider position, and make the wind_set
  313. call as given above.  If the document's length is not an even multiple of
  314. "lines" or "pages" you will have to be careful that incrementing or
  315. decrementing top_wind does not exceed its range of freedom: top_doc to (top_doc
  316. + total_doc - seen_doc).
  317. .PP
  318. If you have such an odd size document, you will also have to make a decision on
  319. whether to violate the line positioning rule so that the slider may be put at
  320. its bottom-most position, or to follow the rule but make it impossible to get
  321. the slider to the extreme of its range.
  322. .SH A COMMON BUG
  323. It is easy to forget that user clicks are not the only things that
  324. affect slider position.  If the window size changes as a result of a
  325. WM_SIZED or WM_FULLED message, the app must also  update its sliders
  326. (if they are present).  This is a good reason to keep the top of
  327. window information in "document units". 
  328. .PP
  329. You can just redo the position calculation with the new "seen_doc" value, and
  330. call  wind_set.  Also remember that changing the size of the
  331. underlying document  (adding or deleting a bottom line, for instance)
  332. must also cause the sliders to be adjusted.
  333. .SH DEPT. OF DIRTY TRICKS
  334. There are two remaining window calls which are useful to advanced programmers.
  335. They require techniques which I have not yet discussed, so you may need to file
  336. them for future reference.
  337. .PP
  338. The AES maintains a quarter-screen sized buffer which is used to save the area
  339. under alerts and menu drop-downs.  It is occasionally useful for the
  340. application to gain access to this buffer for its own use in saving
  341. screen areas with raster copies.  To do so, use:
  342. .FB wind_get()
  343. wind_get(0, WF_SCREEN, &loaddr, &hiaddr, &lolen, &hilen);
  344. .FE
  345. Hiaddr and loaddr are the top and bottom 16-bits (respectively) of the  32-bit
  346. address of the buffer.  Hilen and lolen are the two halves of  its length.
  347. .PP
  348. Due to a preculiarity of the binding you have to reassemble  these
  349. pieces before using them.  (The actual value of WF_SCREEN is 17; this
  350. does not appear in some versions of the GEMDEFS.H file.)
  351. .PP
  352. If you use this buffer, you MUST prevent menus from dropping down by using
  353. either the BEG_UPDATE or BEG_MCTRL wind_update calls.  Failure to do so will
  354. result in your data being destroyed.  Remember to use the matching wind_update:
  355. END_UPDATE or END_MCTRL, when you are done.
  356. .PP
  357. The other useful call enables you to replace the system's desktop definition
  358. with a resource of your choosing.  The call:
  359. .FB wind_set()
  360. wind_set(0, WF_NEWDESK, tree, 0, 0);
  361. .FE
  362. where tree is the 32-bit address of the object tree, will cause the AES to draw
  363. your definition instead of the usual gray or green background. Not
  364. only that, it will continue to redraw this tree with no intervention
  365. on your part. 
  366. .PP
  367. Obviously, the new definition must be carefully built to fit the desktop area
  368. exactly or garbage will be left around the edges.  For the truly sophisticated,
  369. a user-defined object could be used in this tree, with the result that your
  370. application's code would be entered from the AES whenever the desktop was
  371. redrawn.  This would allow you to put VDI pictures or complex images onto the
  372. desktop background.
  373. .SH A SIN OF OMISSION
  374. In the last column, I neglected to mention that strings whose addresses are
  375. passed in the WF_NAME and WF_INFO  wind_set calls must be allocated in a static
  376. data area.  Since the AES remembers the addresses (not the characters), a
  377. disaster may result if the storage has been reused when the window manager next
  378. attempts to draw the window title area.
  379. .SH COMING SOON
  380. This concludes our tour of GEM's basic window management techniques. There have
  381. been some unavoidable glimpses of paths not yet taken (forward references), but
  382. we will return in time.
  383. .PP
  384. On our next excursion, we will take a look at techniques for handling simple
  385. dialog boxes, and start exploring the mysteries of resources and object trees.
  386. .!
  387. .!
  388. .!*****************************************************************************
  389. .!*                                          *
  390. .!*                End Part 2                      *
  391. .!*                                          *
  392. .!*****************************************************************************
  393.